package pl.gigiel.behaviour.steer;

import java.util.List;

import pl.gigiel.behaviour.IBoid;
import pl.gigiel.behaviour.IBoidFeatures;
import pl.gigiel.behaviour.ISteer;
import pl.gigiel.behaviour.exception.BehaviourException;
import pl.gigiel.behaviour.util.CoordinateSystemTransformer;
import pl.gigiel.behaviour.util.Util;

import com.jme.math.Vector3f;

public class AvoidanceSteer implements ISteer {
	private static ISteer steer;

	private AvoidanceSteer() {
	}

	public static ISteer getInstance() {
		if (steer == null) {
			steer = new AvoidanceSteer();
		}
		return steer;
	}

	@Override
	public void init() throws BehaviourException {
		// nothing
	}

	@Override
	public Vector3f force(IBoid boid, float elapsed) throws BehaviourException {
		Vector3f result = new Vector3f();
		List<IBoid> neighbours = boid.getEnvironment().getNeighbours(boid);
		if (!neighbours.isEmpty()) {
			for (IBoid neighbour : neighbours) {
				if (isInsideTunnel(boid, neighbour)) {
					result.addLocal(avoidance(boid, neighbour));
				}
			}
		}
		return result;
	}

	private boolean isInsideTunnel(IBoid boid, IBoid neighbour) {
		boolean result = false;
		IBoidFeatures features = boid.getFeatures();
		Vector3f direction = features.getDirection();
		Vector3f size = features.getSize();
		IBoidFeatures neighbourFeatures = neighbour.getFeatures();
		Vector3f neighbourPosition = neighbourFeatures.getPosition();
		Vector3f neighbourSize = neighbourFeatures.getSize();

		neighbourPosition = CoordinateSystemTransformer.transform(direction, neighbourPosition);
		// neighbor is behind boid
		if (neighbourPosition.y < 0) {
			result = false;
		}
		// neighbor is too far away
		else if (Util.distance(boid, neighbour) > 100) {
			result = false;
		}
		// neighbor is beyond OX
		else if (Util.beyond(0f, size.getX(), neighbourPosition.getX(), neighbourSize.getX()) > 100) {
			result = false;
		}
		// neighbor is beyond OZ
		else if (Util.beyond(0f, size.getZ(), neighbourPosition.getZ(), neighbourSize.getZ()) > 100) {
			result = false;
		}

		return result;
	}

	private Vector3f avoidance(IBoid boid, IBoid neighbour) {
		Vector3f result = null;
		return result;
	}
}
